package edu.gatech.cs2340.teamrocket.control.networking.node;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import edu.gatech.cs2340.teamrocket.control.networking.message.ConnectionClosedMessage;
import edu.gatech.cs2340.teamrocket.control.networking.message.LoginFailureMessage;
import edu.gatech.cs2340.teamrocket.control.networking.message.LoginMessage;
import edu.gatech.cs2340.teamrocket.control.networking.message.LoginSuccessMessage;
import edu.gatech.cs2340.teamrocket.control.networking.message.Message;
import edu.gatech.cs2340.teamrocket.control.networking.messagehandler.MessageHandler;
import edu.gatech.cs2340.teamrocket.control.networking.dialog.Dialog;
import edu.gatech.cs2340.teamrocket.control.networking.exception.TimeoutException;

/**
 * A Node with only one Dialog.
 *
 * @author Joe Tacheron
 */
public class Client extends Node {

    private Dialog dialog;

    public Client(MessageHandler handler) {
        super(handler);
    }

    /**
     * Send a message and don't wait for a response.
     *
     * @param m The message to send.
     */
    public void send(Message m){
        super.send(dialog, m);
    }

    /**
     * Send a message and return after a response is received.
     *
     * @param m The message to send.
     *
     * @return The Message received.
     *
     * @throws TimeoutException If the server did not respond timely.
     */
    public Message sendAndWait(Message m) throws TimeoutException {
        return super.sendAndWait(dialog, m);
    }

    /**
     * This method will log this Client into a remote server. It will start the
     * Client's only Dialog.
     *
     * @param host The IP address of the machine you want to connect to.
     * @param username your username.
     * @param password The password to log into the remote machine.
     *
     * @return The message returned by the remote machine. It may either be a
     * LoginSuccess or LoginFailure message.
     *
     * @throws UnknownHostException If the IP address is unknown.
     * @throws IOException If an IO error occurred.
     * @throws TimeoutException If the server did not respond timely.
     */
    public Message login(String host, String username, String password)
            throws UnknownHostException, IOException, TimeoutException {
        // open connection
        // TODO: have a timeout thread so this method returns if this socket
        // isn't created in a timely fasion.
        Socket socket = new Socket(host, portNum);
        dialog = new Dialog(this, socket);
        dialog.start();

        Message m = null;
        try{
            m = sendAndWait(new LoginMessage(messageCount, username, password));
        }
        catch(TimeoutException e){
            dialog.close();
            throw e;
        }

        if(m instanceof LoginFailureMessage){
            dialog.close();
        }

        if(m instanceof LoginSuccessMessage){
            setRunning(true);
        }

        return m;
    }

    /**
     * Close this Node by closing the one and only Dialog.
     */
    public void close(){
        setRunning(false);
        dialog.send(new ConnectionClosedMessage());
        dialog.close();
    }
}